//-----------------------------------------------------------------------
// <copyright file="UpdateServerCertificate.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <summary>Adds an Http Header to a web site</summary>
//-----------------------------------------------------------------------
namespace Microsoft.Sdc.Tasks.Web.WebSite
{
    using System;
    using Microsoft.Sdc.Tasks.Configuration.Web;
    using Microsoft.Build.Framework;

    /// <summary>
    /// Adds a new Http Custom Header to the specified web site
    /// </summary>
    /// <remarks>
    /// <code><![CDATA[<Web.WebSite.UpdateServerCertificate 
    ///     HostName="hostname" 
    ///     Description="description"
    ///     Thumbprint="thumbprint"
    ///     CertificateStore="certificateStore"/>]]></code>
    /// <para>where:</para>
    /// <para><i>description</i></para>
    /// <para>Web site description for which to set the SSL certificate</para>
    /// <para><i>identifier</i></para>
    /// <para>optional parameter to identify website when 'description' is not used</para>
    /// <para><i>thumbprint</i></para>
    /// <para>Thumbprint of the certificate to use (the certificate should already be in a machine certificate Store)</para>
    /// <para><i>CertificateStore (Required)</i></para>
    /// <para>The store in which to find the certificate, this must be a machine store</para>
    /// <para><i>hostname</i></para>
    /// <para>Host on which  to add the Http Custom Header (defaults to loaclhost)</para>
    /// </remarks>
    /// <example>
    /// <code><![CDATA[
    /// <Project>
    ///     <Target Name="Test" >
    ///    <UpdateServerCertificate 
    ///         Description="DcPortal" 
    ///         thumbprint="df77c72cb611bd61d26185bb278ca0dbcb3c4918" 
    ///         CertificateStore="MY">            
    ///     </UpdateServerCertificate>    
    ///     </Target>
    /// </Project>
    /// ]]></code>    
    /// </example>    
    public class UpdateServerCertificate : TaskBase
    {
        private string description;
        private string thumbprint;
        private string certificateStore;
        private string identifier;
        private string sslAccessFlags;
        private string machineName = "localhost";

        /// <summary>
        /// Machine to operate on
        /// </summary>
        public string MachineName
        {
            get { return this.machineName; }
            set { this.machineName = value; }
        }

        /// <summary>
        /// Name of the store in which the SSL certificate is stored
        /// </summary>
        /// <value>a string description</value>
        /// <remarks>Usually set to "MY"</remarks>
        [Required]
        public string CertificateStore
        {
            get { return (this.certificateStore ?? String.Empty); }
            set { this.certificateStore = value; }
        }

        /// <summary>
        /// Description of web site to be updated
        /// </summary>
        /// <value>A valid web site description</value>
        /// <remarks>If this parameter is not specified you must specify the site 
        /// for the site you wish to apply the binding to</remarks>
        public string Description
        {
            get { return (this.description ?? String.Empty); }
            set { this.description = value; }
        }

        /// <summary>
        /// Optional Identifier for website to update where Website description has not been provided
        /// </summary>
        /// <value>A valid host name</value>
        public string Identifier
        {
            get { return (this.identifier ?? String.Empty); }
            set { this.identifier = value; }
        }

        /// <summary>
        /// The thumbrint for the certificate to use for SSL
        /// </summary>
        /// <value>A valid web site thumbprint</value>
        /// <remarks>This certificate should already be installed in the apporiate store. It should be a Server Authentication certificate 
        /// </remarks>
        [Required]
        public string Thumbprint
        {
            get { return (this.thumbprint ?? String.Empty); }
            set { this.thumbprint = value; }
        }

        /// <summary>
        /// SslAccessFlags. Configures the ssl restrictions for teh site that is to be updated.
        /// </summary>
        /// <value>integer</value>
        /// <remarks>
        /// 
        /// The following values are valid. Use a space separated list to combine flags.
        /// Or simply supply the integer value required.
        /// 
        /// Defaults to SslAny (SSL not required)
        /// 
        ///  SslAny = 0x00000000
        ///  RequireSsl = 0x00000008
        ///  RequireSsl128 = 0x00000100
        ///  MapClientCert = 0x00000080
        ///  RequestClientCert = 0x00000020
        ///  RequireClientCert = 0x00000040
        ///  
        /// </remarks>
        public string SslAccessFlags
        {
            get { return (this.sslAccessFlags ?? String.Empty); }
            set { this.sslAccessFlags = value; }
        }

        /// <summary>
        /// Performs the action of this task.
        /// </summary>
        protected override void InternalExecute()
        {
            ServerCertificate.SslAccessFlags flags = ServerCertificate.SslAccessFlags.SslAny;
            int id = Utilities.CheckWebSiteDescriptionOrIdentifier(this.description, this.identifier, "UpdateServerCertificate", this.MachineName);
            if (WebSite.Exists(this.MachineName, id))
            {
                Microsoft.Sdc.Tasks.Configuration.Web.WebSite web = WebSite.Load(this.MachineName, id);
                Microsoft.Sdc.Tasks.Configuration.Web.ServerCertificate serverCertificate = new Microsoft.Sdc.Tasks.Configuration.Web.ServerCertificate(web);

                if (this.sslAccessFlags != null)
                {
                    flags = ParseSslFlags(this.sslAccessFlags);
                }

                serverCertificate.Update(this.thumbprint, this.certificateStore, flags);
                web.Save();
            }
        }

        private static ServerCertificate.SslAccessFlags ParseSslFlags(string flagString)
        {
            int sslFlags;

            // we allow flags to be specified as an int or as a space separated list of named flags
            if (!int.TryParse(flagString, out sslFlags))
            {
                string[] flagStringSplit = flagString.Split(' ');
                foreach (string splitItem in flagStringSplit)
                {
                    int flag = (int) Enum.Parse(typeof(ServerCertificate.SslAccessFlags), splitItem, true);
                    sslFlags = sslFlags | flag;
                }
            }

            return (ServerCertificate.SslAccessFlags) sslFlags;
        }
    }
}